#include "LecteurPhraseAvecTable.h"
 
#include <stdlib.h>
#include <iostream>
using namespace std;

////////////////////////////////////////////////////////////////////////////////
LecteurPhraseAvecTable::LecteurPhraseAvecTable(string nomFich) :
	ls(nomFich), ts() {
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::analyse() {
	programme();
	cout << "Syntaxe correcte." << endl;
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::programme() {
// <programme> ::= debut <seqInst> fin <EOF>

	sauterSymCour("debut");
	seqInst();
	sauterSymCour("fin");
	testerSymCour("<FINDEFICHIER>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::seqInst() {
// <seqInst> ::= <inst> ; { <inst> ; }

	do {
		inst();
		sauterSymCour(";");
	} while (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour() == "si" || ls.getSymCour() == "tantque" || ls.getSymCour() == "repeter" || ls.getSymCour() == "lire" || ls.getSymCour()=="pour" || ls.getSymCour()=="ecrire");
	// tant que le symbole courant est un debut possible d'instruction...
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::inst() {
// <inst> ::= <affectation> | <instSi> | <instTq> | <instRepeter> | <instLire> | <instEcrire>


	
        if (ls.getSymCour()=="<VARIABLE>")
                affectation();
        else if (ls.getSymCour()=="si") // on lance la "conditionr qui contiendra elle-meme des instructions. (condition = ExpBool)
                instSi();
        else if (ls.getSymCour()=="tantque") // idem que if
                instTq();
        else if (ls.getSymCour()=="repeter") // idem que if
                instRepeter();        
        else if (ls.getSymCour()=="lire") // idem que if
                instLire();
        else if (ls.getSymCour()=="pour") // idem que if
                instPour();        
        else if (ls.getSymCour()=="ecrire") // idem que if
                instEcrire();
        else
        erreur("<inst>");

}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::affectation() {
// <affectation> ::= <variable> = <expression>

	//sauterSymCour("<VARIABLE>");
	testerSymCour("<VARIABLE>");
	ts.chercheAjoute(ls.getSymCour());
	ls.suivant();
	sauterSymCour("=");
	expression();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::expression() {
// <expression> ::= <facteur> { <opBinaire> <facteur> }

	terme();
	while (ls.getSymCour()=="+" || ls.getSymCour()=="-") {
		opAdd();
		terme();
	}
}


////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::facteur() {
// <facteur> ::= <entier>  |  <variable>  |  - <facteur>  |  ( <expression> )

	if (ls.getSymCour()=="<VARIABLE>" || ls.getSymCour()=="<ENTIER>" || ls.getSymCour()=="<CHAINE>" ){
		ts.chercheAjoute(ls.getSymCour());
		ls.suivant();
	} else if (ls.getSymCour()=="-" || ls.getSymCour()=="non") {
                opUnaire();
                ls.suivant();
		facteur();
	} else if (ls.getSymCour()=="(") {
		ls.suivant();
		expression();
		sauterSymCour(")");
	} else
		erreur("<facteur>");
}
////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseAvecTable::terme(){
// <terme> ::= <facteur> { <opMult> <facteur> }
        facteur();

        while (ls.getSymCour()=="*" || ls.getSymCour()=="/") {
                opMult();
                facteur();
        }
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::opAdd(){
    if (ls.getSymCour()=="+" || ls.getSymCour()=="-")
                ls.suivant();
        else
                erreur("<opAdd>");

}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseAvecTable::opMult(){
     if (ls.getSymCour()=="*" || ls.getSymCour()=="/")
                ls.suivant();
      else
                erreur("<opMult>");

}
////////////////////////////////////////////////////////////////////////////////
//void LecteurPhraseAvecTable::opBinaire() {
//// <opBinaire> ::= + | - | *  | /
//
//	if (ls.getSymCour()=="+" || ls.getSymCour()=="-" || 
//		ls.getSymCour()=="*" || ls.getSymCour()=="/" )
//		ls.suivant();
//	else
//		erreur("<opBinaire>");
//}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::opBool(){
    	if (ls.getSymCour()=="et" ||ls.getSymCour()=="ou" )
		ls.suivant();
        else
		erreur("<opBool>");
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::opUnaire()
// <opUnaire> ::= - | non
{

        if (ls.getSymCour()=="-" || ls.getSymCour()=="non")
                ls.suivant();
        else
                erreur("<opUnaire>");

}


////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::expBool()
// <expBool> ::= <relation> { <opBool> <relation> }
{
        if (ls.getSymCour()=="non") {
        sauterSymCour("non");
        }
        relation();
        while (ls.getSymCour()=="et" || ls.getSymCour()=="ou") {
                opBool();
                relation();
        }
}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::opRel()
// <opRel> ::= == | != | < | <= | > | >=
{

        if (ls.getSymCour()=="==" || ls.getSymCour()=="!=" ||
                ls.getSymCour()=="<" || ls.getSymCour()=="<=" ||
                ls.getSymCour()==">" || ls.getSymCour()==">=")
                ls.suivant();
        else
                erreur("<opRel>");

}

////////////////////////////////////////////////////////////////////////////////

void LecteurPhraseAvecTable::relation()
// <relation> ::= <expBool> { <opRel> <expBool> }
// <expression> { <opRel> <expression> }
{
        expression();
        while (ls.getSymCour()=="==" || ls.getSymCour()=="!=" ||
                        ls.getSymCour()=="<" || ls.getSymCour()=="<=" ||
                        ls.getSymCour()==">" || ls.getSymCour()==">=") {
                opRel();
                expression();
        }

}
////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::instSi()
//  <instSi> ::= si ( <expBool> ) <seqInst> { sinonsi ( <expBool> ) <seqInst> }
//  [ sinon <seqInst> ] finsi
{
        sauterSymCour("si");
        sauterSymCour("(");
        expBool();
        sauterSymCour(")");
        seqInst();
        while (ls.getSymCour()=="sinonsi") {
                ls.suivant();
                sauterSymCour("(");
                expBool();
                sauterSymCour(")");
                seqInst();
        }
        if (ls.getSymCour()=="sinon") {
                ls.suivant();
                seqInst();
        }
        sauterSymCour("finsi");

}
        

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::instTq()
// <instTq> ::= tantque ( <expBool> ) <seqInst> fintantque
{
        sauterSymCour("tantque");
        sauterSymCour("(");
        expBool();
        sauterSymCour(")");
        seqInst();
        sauterSymCour("fintantque");

}

void LecteurPhraseAvecTable::instPour()
//<instPour> ::= pour (<inst>; <relation>; <inst>) faire <seqInst> finfaire;
{
    sauterSymCour("pour");
    sauterSymCour("(");
    inst();
    sauterSymCour(";");
    relation();
    sauterSymCour(";");
    inst();
    sauterSymCour(")");
    sauterSymCour("faire");
    seqInst();
    sauterSymCour("finfaire");
    
    
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::instRepeter()
// <instRepeter> ::= repeter <seqInst> jusqua ( <expBool> )
{       
        sauterSymCour("repeter");
        seqInst();
        sauterSymCour("jusqua");
        sauterSymCour("(");
        expBool();
        sauterSymCour(")");

}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::instLire()
// <instLire> ::= lire ( <variable> )
{
        sauterSymCour("lire");
        sauterSymCour("(");
        if (ls.getSymCour()=="<VARIABLE>") {
                facteur();
                sauterSymCour(")");
        }
        else
                erreur("<variable>");
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::instEcrire()
// <instEcrire> ::= ecrire ( <string> )
{
        sauterSymCour("ecrire");
        sauterSymCour("(");
        if (ls.getSymCour()=="<STRING>") {
                ls.suivant();
        }
        else
                expression();
        sauterSymCour(")");
}



////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::testerSymCour(string ch) {
	if (ls.getSymCour() != ch) {
		cout << endl << "-------- Erreur ligne " << ls.getLigne()
				<< " - Colonne " << ls.getColonne() << endl << "   Attendu : "
				<< ch << endl << "   Trouve  : " << ls.getSymCour() << endl
				<< endl;
		exit(0); // plus tard, on levera une exception
	}
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::sauterSymCour(string ch) {
	testerSymCour(ch);
	ls.suivant();
}

////////////////////////////////////////////////////////////////////////////////
void LecteurPhraseAvecTable::erreur(string mess) {
	cout << endl << "-------- Erreur ligne " << ls.getLigne() << " - Colonne "
			<< ls.getColonne() << endl << "   Attendu : " << mess << endl
			<< "   Trouve  : " << ls.getSymCour() << endl << endl;
	exit(0); // plus tard, on levera une exception

}
